package com.yx.coredata.module.user.controller;

import com.yx.coredata.common.ConsHint;
import com.yx.coredata.common.Constant;
import com.yx.coredata.common.CurrentUser;
import com.yx.coredata.common.RandomImage;
import com.yx.coredata.common.exception.ServiceException;
import com.yx.coredata.common.result.JsonPageResult;
import com.yx.coredata.common.result.JsonResult;
import com.yx.coredata.module.user.domain.User;
import com.yx.coredata.module.user.service.UserService;
import com.yx.coredata.module.user.vo.PasswordVO;
import com.yx.coredata.module.user.vo.UserVo;
import com.yx.coredata.utils.MD5Util;
import com.yx.lib.utils.DigestUtils;
import com.yx.lib.utils.StringHandle;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.crazycake.shiro.SerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Map;

/**
 * Created by liukailong on 2017/2/9.
 */
@RestController
@RequestMapping(value = "/user")
public class UserController {

    private final static Logger log = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;


    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public JsonResult login(@RequestBody UserVo user, HttpServletRequest req){
        log.debug(" to login");
        Subject subject = SecurityUtils.getSubject();
        try {
            // 效验验证码
//            isValidateCode(user.getValidateCode(), subject);
            Session session = SecurityUtils.getSubject().getSession();
            String code = (String) session.getAttribute("validateCode");
            String submitCode =user.getValidateCode();
            if (StringUtils.isEmpty(submitCode) || !StringUtils.equals(code, submitCode.toLowerCase())) {
                return new JsonResult(false, "验证码输入错误，请重新输入！");
            }

            UsernamePasswordToken token = new UsernamePasswordToken();
            token.setUsername(user.getAccount());
            token.setPassword(user.getPassword().toCharArray());
            subject.login(token);
        }catch (Exception e){
            log.error("",e);
            User user1 = userService.findUserByAccount(user.getAccount());
            if(user1 != null && user1.getFlag() == Constant.ZERO){
                return new JsonResult(false, "登录失败！该用户已禁用!");
            }else{
                return new JsonResult(false, "登录失败！用户名或密码错误!");
            }

        }
        return new JsonResult(true, "ok");
    }

    /**
     * 效验验证码是否正确
     * @param code
     * @param subject
     */
    public void isValidateCode(String code, Subject subject){
        String validateCode = (String) subject.getSession().getAttribute("validateCode");
        if (code == null || !code.equals(validateCode)) {
            throw new ServiceException("验证码输入错误，请重新输入！");
        }
    }

    /**
     * 生成验证码
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @RequestMapping(value = "/validateCode",method = RequestMethod.GET)
    public void validateCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Cache-Control", "no-cache");
        String verifyCode = RandomImage.generateTextCode(RandomImage.TYPE_NUM_LOWER, 4, null);
        Session session = SecurityUtils.getSubject().getSession();
        session.removeAttribute("validateCode");
        session.setAttribute("validateCode", verifyCode);
        response.setContentType("image/jpeg");
        BufferedImage bim = RandomImage.generateImageCode(verifyCode, 90, 30, 5, true, Color.WHITE, Color.BLUE, null);
        ImageIO.write(bim, "JPEG", response.getOutputStream());
    }

    /**
     * 登录成功后单独调用获取用户信息
     * @return
     */
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    public JsonResult getOnlineUserInfo(){
        Subject subject = SecurityUtils.getSubject();
        Map<String,Object> mapUser = (Map<String,Object>) SerializeUtils.deserialize((byte[]) subject.getSession().getAttribute("user"));

        return new JsonResult(true, "ok", mapUser);
    }

    /**
     * 退出登录
     * @return
     * @author liukailong
     * @since 2017-03-07
     */
    @RequestMapping(value = "/logout",method = RequestMethod.POST)
    public JsonResult logout() {
        Subject subject = SecurityUtils.getSubject();

        if (subject.isAuthenticated()) {
            subject.logout();
        }
        return new JsonResult(true, "退出成功");
    }

    /**
     *@Author liukailong
     *@Date 2017/3/6
     *@Description 新增
     */
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public JsonResult add(@RequestBody UserVo user){
        Assert.notNull(user.getAccount(), MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"账号"));
        Assert.notNull(user.getName(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"姓名"));
        Assert.notNull(user.getTel(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"电话"));
        Assert.notNull(user.getRole(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"角色"));
        Assert.notNull(user.getProfessionId(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"专业id"));
//        Assert.isTrue(user.getSubjectIds().size()>0,MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"学科"));
        //默认密码
        user.setPassword(DigestUtils.getStringMD5Code(Constant.PASSWORD));
        return userService.add(user);
    }

    /**
     *@Author liukailong
     *@Date 2017/3/6
     *@Description 禁用
     */
    @RequestMapping(value = "/stop",method = RequestMethod.PUT)
    public JsonResult delete(@RequestBody User user){
        Assert.isTrue(0 < user.getId(), MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"ID"));
        userService.stop(user);
        if(user.getFlag() == Constant.ZERO){
            return new JsonResult(true,"禁用成功!");
        }else{
            return new JsonResult(true,"启用成功!");
        }
    }

    /**
     *@Author liukailong
     *@Date 2017/3/6
     *@Description 修改
     */
    @RequestMapping(value = "/edit",method = RequestMethod.PUT)
    public JsonResult edit(@RequestBody UserVo user){
        Assert.isTrue(0 < user.getId(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"ID"));
        Assert.notNull(user.getName(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"姓名"));
        Assert.notNull(user.getTel(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"电话"));
        //Assert.notNull(user.getProfessionId(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"专业类id"));
//        Assert.isTrue(user.getSubjectIds().size()>0,MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"学科"));
        return userService.edit(user);
    }

    /**
     *@Author liukailong
     *@Date 2017/3/6
     *@Description 列表
     *@params keyword：关键字
     *         pageNo:当前页码
     *         pageSize:每页条数
     */
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public JsonPageResult list(@RequestParam(name = "keyword",required = false) String keyword,
                               @RequestParam("pageNo") int pageNo,
                               @RequestParam("pageSize") int pageSize,
                               @RequestParam("role") int role){
        Assert.isTrue(0 <= pageNo, MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,ConsHint.PAGE_NO));
        Assert.isTrue(0 <= pageSize, MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,ConsHint.PAGE_SIZE));
        return userService.list(pageNo,pageSize, StringHandle.escape4Like(keyword),role);
    }

    /**
     * @Author liukailong
     * @Date 2017/3/6
     * @Description 明细
     * @params id
     */
    @RequestMapping(value = "/detail",method = RequestMethod.GET)
    public JsonResult detail(@RequestParam(value = "id") Long id){
        Assert.isTrue(0 <= id, MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"ID"));
        return userService.getUserById(id);
    }

    /**
     *@Author liukailong
     *@Date 2017/3/7
     *@Description 修改密码
     *@params new 新密码 old 旧密码
     */
    @RequestMapping(value = "/password",method = RequestMethod.POST)
    public JsonResult modifyPassword(@RequestBody PasswordVO passwordVO){
        Assert.notNull(passwordVO.getNewPassword(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"新密码"));
        Assert.notNull(passwordVO.getOldPassword(),MessageFormat.format(ConsHint.ARG_VALIDATION_ERR,"旧密码"));
        User user = userService.selectByPrimaryKey(CurrentUser.getUser().getId());

        //判断与旧密码是否相同
        if(!passwordVO.getOldPassword().equals( user.getPassword())){
            return new JsonResult(false,"旧密码错误，请重新输入");
        }

        //修改为新密码
        user.setPassword(passwordVO.getNewPassword());

        userService.updateByPrimaryKeySelective(user);
        return new JsonResult(true,ConsHint.UPDATE_SUCCESS);
    }

    /**
     * 权限异常处理
     * @param response
     * @return
     */
    @RequestMapping(value = "/403")
    public JsonResult sessionTimeOut(HttpServletResponse response) {
        response.setStatus(403);
        return new JsonResult(false,"权限异常，请重新登录");
    }

    /**
     * 根据id重置密码 置为123456
     *
     * @param id id
     * @return JsonResult
     * @author hesufang
     * @since 2015-10-15.
     */
    @RequestMapping(value = "/resetPassword", method = RequestMethod.POST)
    public JsonResult resetPassword(@RequestParam("id") long id) {

        Assert.isTrue(id > 0, MessageFormat.format(ConsHint.ARG_VALIDATION_ERR, "用户ID"));

        User user = new User();
        user.setId(id);
        user.setPassword(MD5Util.getMD5(Constant.PASSWORD));

        userService.updateByPrimaryKeySelective(user);

        return new JsonResult(true,  "重置密码成功");
    }
}
